﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Amf4Asmx.Web
{
    public static class TypeHelper
    {
        private static Dictionary<Type, WebTypeData> types = new Dictionary<Type, WebTypeData>();
        public static object Instantiate(Type type, object p)
        {
            if (p != null && type == p.GetType())
            {
                return p;
            }
            else if (type.IsEnum)
            {
                return Enum.Parse(type, p as string);
            }
            else if (typeof(System.Xml.XmlNode).IsAssignableFrom(type))
            {
                if (type == typeof(System.Xml.XmlDocument))
                {
                    return p;
                }

                return (p as System.Xml.XmlDocument).DocumentElement;
            }
            else if (type.IsArray && p is Array)
            {
                Array fromArray = (p as Array);
                Array array = Array.CreateInstance(type.GetElementType(), fromArray.Length);
                for (int j = 0; j < fromArray.Length; j++)
                {
                    array.SetValue(TypeHelper.Instantiate(type.GetElementType(), fromArray.GetValue(j)), j);
                }
                return array;
            }
            else if (type == typeof(string))
            {
                if (p == null)
                {
                    return null;
                }
                return p.ToString();
            }
            else if (type.IsPrimitive)
            {
                return Convert.ChangeType(p, type);
            }
            else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                if (p == null)
                {
                    return null;
                }
                else
                {
                    return Instantiate(type.GetGenericArguments()[0], p);
                }
            }
            else
            {
                WebTypeData data = GetWebType(type);
                return data.Instantiate(p);
            }
        }

        static WebTypeData GetWebType(Type type)
        {
            if (!types.ContainsKey(type))
            {
                lock (types)
                {
                    if (!types.ContainsKey(type))
                    {
                        types.Add(type, new WebTypeData(type));
                    }
                }
            }
            return types[type];
        }

        internal static AmfObjects.NamedDictionary GetNamedDictionaryFor(object p)
        {
            if (p is IDictionary<string, object>)
            {
                AmfObjects.NamedDictionary result = new AmfObjects.NamedDictionary();
                foreach (KeyValuePair<string, object> kvp in p as IDictionary<string, object>)
                {
                    result.Properties[kvp.Key] = (p as IDictionary<string, object>)[kvp.Key];
                }
                return result;
            }
            else
            {
                WebTypeData data = GetWebType(p.GetType());
                return data.GetNamedDictionary(p);
            }
        }
    }
}
